﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using EasyLucky.Common;
using EasyLucky.Dal.Dal;
using EasyLucky.Dal.Entity;
using EasyLucky.Message.Messages;
using EasyLucky.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace EasyLucky.ViewModels
{
    public class LuckyViewModel:ObservableObject
    {

        private LuckyDataM dataM;

        public LuckyDataM DataM
        {
            get { return dataM; }
            set { SetProperty(ref dataM, value); }
        }

        private GiftDal giftDal;

        private UserDal userDal;

        private LuckyDal luckyDal;

        private WinnerDal winnerDal;

        private Task task;

        private CancellationToken token;

        private CancellationTokenSource cts;

        private TextBlock btn;

        public LuckyViewModel()
        {
            this.DataM = new LuckyDataM()
            {
                Users = new ObservableCollection<User>(),
                Gifts = new ObservableCollection<GiftM>(),
                Luckys = new ObservableCollection<Lucky>(),
                LostUsers = new List<User>(),
                Winners = new List<Winner>(),
                CurLucky = new LuckyItemM(),
                CurUsers=new ObservableCollection<User>(),
            };
            cts = new CancellationTokenSource();
            token=cts.Token;
        }


        #region Loaded

        private IRelayCommand loadedCommand;

        public IRelayCommand LoadedCommand
        {
            get { return loadedCommand ??= new RelayCommand<RoutedEventArgs>(Loaded); }
        }

        private void Loaded(RoutedEventArgs e)
        {
            if(e.Source is Views.Lucky)
            {
                var control  = e.Source as Views.Lucky;
                if(control != null)
                {
                    this.btn = control.btn;
                    this.btn.Focus();
                }
            }
            if(giftDal == null)
            {
                this.giftDal= new GiftDal();
                var entitys = this.giftDal.QueryAll();
                var gifts = new List<GiftM>();
                foreach(var entity in entitys)
                {
                    var baseDir = AppDomain.CurrentDomain.BaseDirectory;
                    var fullPath = Path.Combine(baseDir, entity.ImageUrl.StartsWith("\\")?entity.ImageUrl.Substring(1):entity.ImageUrl);
                    var gift = new GiftM()
                    {
                        Id = entity.Id,
                        Name = entity.Name,
                        ImageUrl =fullPath,
                    };
                    gift.ReadImage();
                    gifts.Add(gift);
                }
                this.DataM.Gifts = new ObservableCollection<GiftM>(gifts);
            }
            if(userDal== null)
            {
                this.userDal=new UserDal();
                var entitys = this.userDal.QueryAll();
                var users = new List<User>();
                foreach(var entity in entitys)
                {
                    var user = new User()
                    {
                        Id = entity.Id,
                        Name = entity.Name,
                    };
                    users.Add(user);
                }
                this.DataM.Users = new ObservableCollection<User>(users);
            }
            if(luckyDal== null)
            {
                this.luckyDal= new LuckyDal();
                var entitys = this.luckyDal.QueryAll();
                var luckys = new List<Lucky>();
                foreach (var entity in entitys)
                {
                    var lucky = new Lucky()
                    {
                        Id = entity.Id,
                        Name = entity.Name,
                        Count = entity.Count,
                        GiftId = entity.GiftId,
                        Level = entity.Level,
                        LuckyOrder = entity.LuckyOrder,
                        LuckyType = entity.LuckyType,
                    };
                    luckys.Add(lucky);
                }
                this.DataM.Luckys = new ObservableCollection<Lucky>(luckys.OrderBy(item=>item.LuckyOrder));
            }
            if (this.DataM.CurLucky.Lucky == null)
            {
                this.DataM.CurLucky.Lucky = this.DataM.Luckys.FirstOrDefault();
                var giftId = this.DataM.CurLucky.Lucky.GiftId;
                this.DataM.CurLucky.Gift = this.DataM.Gifts.FirstOrDefault(item => item.Id == giftId);
                var count = this.DataM.CurLucky.Lucky.Count;
                if(count > 4)
                {
                    this.DataM.Row = 2;
                    this.DataM.Column = (int)Math.Ceiling(count * 1.0d / 2);
                }
            }
        }

        #endregion

        #region MouseDown

        private IRelayCommand mouseDownCommand;

        public IRelayCommand MouseDownCommand
        {
            get { return mouseDownCommand ??= new RelayCommand<MouseButtonEventArgs>(MouseDown); }
        }

        private void MouseDown(MouseButtonEventArgs e)
        {
            if(e.LeftButton==MouseButtonState.Pressed)
            {
                this.btn.Focus();
            }
        }

        #endregion

        #region KeyDown

        private IRelayCommand keyDownCommand;

        public IRelayCommand KeyDownCommand
        {
            get { return keyDownCommand ??= new RelayCommand<KeyEventArgs>(KeyDown); }
        }

        private void KeyDown(KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
            {
                if (this.DataM.State == 0)
                {
                    Start();
                }
                else
                {
                    Stop();
                }
            }
            if(e.Key == Key.Down)
            {
                Next();
            }
        }

        #endregion

        #region 开始，暂停

        private void Start()
        {
            cts = new CancellationTokenSource();
            token = cts.Token;
            task = Task.Run(() =>
            {
                var luckyCount = this.DataM.CurLucky.Lucky.Count;
                var userCount = this.DataM.Users.Count;
                var random = new Random(DateTime.Now.Second);
                var rnd = random.Next(0,userCount);
                int index = rnd;
                if(index+luckyCount > userCount)
                {
                    index = userCount - luckyCount;
                }
                
                while (!token.IsCancellationRequested)
                {
                    var users=new List<User>();
                    if(index+luckyCount > userCount)
                    {
                        //读到最后再循环读取
                        for(int i = index; i < userCount; i++)
                        {
                            users.Add(this.DataM.Users[i]);
                        }
                        for(int i = 0; i < luckyCount - (userCount - index); i++)
                        {
                            users.Add(this.DataM.Users[i]);
                        }
                        index = luckyCount - (userCount - index);
                    }
                    else
                    {
                        //顺序读取
                        for (int i = index; i < index+luckyCount; i++)
                        {
                            users.Add(this.DataM.Users[i]);
                        }
                        index=index+luckyCount;
                    }
                    Application.Current.Dispatcher.Invoke(new Action(() =>
                    {
                        this.DataM.CurUsers = new ObservableCollection<User>(users);
                    }));
                    Thread.Sleep(100);
                }
            },token);
            this.DataM.State = 1;
        }

        private void Stop()
        {
            cts.Cancel();
            //获取当前获奖名单
            var users = this.DataM.CurUsers.ToList();
            var lucky = this.DataM.CurLucky.Lucky;
            if (winnerDal == null)
            {
                winnerDal = new WinnerDal();
            }
            foreach(var user in users)
            {
                var entity = new WinnerEntity()
                {
                    UserId = user.Id,
                    LuckyId = lucky.Id,
                    WinnerTime = DateTime.Now,
                };
                int id= this.winnerDal.AddWinner(entity);
                if(id <1)
                {
                    MessageBox.Show("添加失败");
                    break;
                }
            }
            //
            for(int i=0; i<users.Count; i++)
            {
                var user = users[i];
                this.DataM.Users.Remove(user);//从列表中移除中奖名单
            }
            this.DataM.State=0;
        }

        private void Next()
        {
            int order = this.DataM.CurLucky.Lucky.LuckyOrder;
            var next = this.DataM.Luckys.FirstOrDefault(item => item.LuckyOrder > order);
            if (next != null)
            {
                this.DataM.CurLucky.Lucky = next;
                var giftId = this.DataM.CurLucky.Lucky.GiftId;
                this.DataM.CurLucky.Gift = this.DataM.Gifts.FirstOrDefault(item => item.Id == giftId);
                if (next.Count > 4)
                {
                    this.DataM.Row = 2;
                    this.DataM.Column = (int)Math.Ceiling(next.Count * 1.0d / 2);
                }
                this.DataM.State = 0;
                this.DataM.CurUsers.Clear();
            }
            else
            {
                WeakReferenceMessenger.Default.Send(new StateChangedMessage(2));
            }
        }


        #endregion
    }
}
